package com.sjh.lib_app.net

import android.util.Base64
import com.blankj.utilcode.util.EncryptUtils
import com.sjh.baseutils.println
import com.sjh.net.StringResponseBody
import com.sjh.net.interceptor.BaseInterceptor
import okhttp3.Interceptor
import okhttp3.Response
import org.json.JSONArray
import org.json.JSONObject

/**
 * 解密
 * Created by Extends on 2018/2/5/005
 */
class EncryptInterceptor : BaseInterceptor() {
    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request()

        var isNotEncrypt = false
        if (request.header("noEncrypt") != null) {
            isNotEncrypt = true
            //移除noEncrypt响应头,以免出现未知bug
            request = request.newBuilder().removeHeader("noEncrypt").build()
        }

        val response = chain.proceed(request)
        if (isNotEncrypt) {
            return response
        }
        //获取服务器返回的数据
        var j: JSONObject? = null
        val responseBody = getResponBodyString(response)!!
        try {
            j = JSONObject(responseBody)
        } catch (e: Exception) {
            e.printStackTrace()
//            if (AppConfig.isSendEmail()) {
//                //服务器报错了，给杨彬发送邮件
//                val time = TimeUtils.getNowString()
//                val subject = "$time \t 接口报错\t${request.url()}"
//                val headers = buildString {
//                    val names = request.headers().names()
//                    for (name in names) {
//                        request.headers().get(name)
//                        appendln("\t\t$name : ${request.headers().get(name)}")
//                    }
//                }
//
//                val context = """
//请求时间：  $time
//报错设备：  ${Build.BRAND + " " + Build.MODEL}
//接口地址：  ${request.url()}
//请求方式：  ${request.method()}
//请求头：
//$headers
//请求body：  ${getRequestParams(request) ?: ""}
//返回数据：  $responseBody
//            """.trimIndent()
//                sendSelfEmail(subject, context, arrayOf("2500135238@qq.com", "2563892038@qq.com"))
//                Log.e("HttpError", subject)
//            }

            throw Exception("服务器错误，请稍后再试")
        }

        //判断是否是加密后的数据
        if (!j.has("is_secret") || j.optInt("is_secret") != 1) {
            //说明数据没有加密
            return response
        }

        if (j!!.has("data")) {
            val jo = j.getJSONObject("data")
            var json = ""
            try {
                //1. 以"."分割data.secret字符串
                val temp = jo.getString("secret").split(".")
                val iv = Base64.decode(temp[1], Base64.DEFAULT)
                //2. 用RSA公钥解密分割出来的第一个字符串，得到AES密钥。
                //填充方式：PKCS1_PADDING
                val aes =
                    RSAUtils.decryptByteArrayByPublicKey(
                        RSAUtils.loadPublicKey(
                            RSAUtils.publicKey), temp[0])
                //3. 使用AES密钥解密data.data字符串，在通过Base64解密可得到一个json数据
                //加密模式：CBC
                //填充方式：pkcs5padding、pkcs7padding、zeropadding均可解密
                //偏移量iv：第一步分割出来的第二个字符串经过base64解密后即为偏移量
                val dataJson =
                    String(Base64.decode(AESUtils.decrypt(Base64.decode(jo.getString("data"), Base64.DEFAULT), aes, iv)!!, Base64.DEFAULT))
                val joo = JSONObject(dataJson)
                //4. 校验数据安全性
                // 对data进行MD5计算，得到32位小写md5值，与sign进行对比

                val isEquals = EncryptUtils.encryptMD5ToString(joo.getString("data")).equals(joo.getString("sign"),true)

                if (!isEquals) {
                    "校验失败".println()
                } else {
                    // 5. 对data进行Base64解密得到最终结果
                    json = String(Base64.decode(joo.getString("data"), Base64.DEFAULT))

                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
            j.remove("data")
            when (json) {
                "{}", "[]" -> j.put("data", null)
                else -> when (json[0]) {
                    '{' -> j.put("data", JSONObject(json))
                    '[' -> j.put("data", JSONArray(json))
                    'n', 'N' -> j.put("data", null)
                    else -> j.put("data", json)
                }
            }
        } else {
            j.put("data", null)
        }
        return response.newBuilder()
            .body(StringResponseBody(j.toString()))
            .build()
    }
}